﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SettingManager.cs" company="arvystate.net">
//   arvystate.n et
// </copyright>
// <summary>
//   The setting manager.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace PresentationAid.Settings
{
    using System;
    using System.IO;
    using System.Xml.Serialization;

    using NLog;

    /// <summary>
    /// The setting manager.
    /// </summary>
    [XmlRoot]
    public class SettingManager
    {
        #region Static Fields

        /// <summary>
        /// The logger.
        /// </summary>
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        /// <summary>
        /// Singleton private instance
        /// </summary>
        private static SettingManager instance;

        #endregion

        #region Fields

        /// <summary>
        /// The auto update .
        /// </summary>
        private bool autoUpdate;

        /// <summary>
        /// The can minimize to tray setting.
        /// </summary>
        private bool canMinimizeToTray;

        /// <summary>
        /// The debug mode setting.
        /// </summary>
        private bool debugMode;

        /// <summary>
        /// The display overlay setting.
        /// </summary>
        private bool displayOverlay;

        /// <summary>
        /// The display popup notifications setting.
        /// </summary>
        private bool displayPopupNotifications;

        /// <summary>
        /// The gesture engine mapping setting.
        /// </summary>
        private string gestureEngineMapping;

        /// <summary>
        /// The gesture engine type setting.
        /// </summary>
        private int gestureEngineType;

        /// <summary>
        /// The language setting.
        /// </summary>
        private int language;

        /// <summary>
        /// The last update check setting.
        /// </summary>
        private long lastUpdateCheck;

        /// <summary>
        /// The move to tray setting.
        /// </summary>
        private bool moveToTray;

        /// <summary>
        /// The no presenter overlay setting.
        /// </summary>
        private bool noPresenterOverlay;

        /// <summary>
        /// The use xml setting.
        /// </summary>
        private bool useXml;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Prevents a default instance of the <see cref="SettingManager"/> class from being created.
        /// </summary>
        private SettingManager()
        {
            // Default settings
            this.canMinimizeToTray = true;
            this.displayPopupNotifications = true;
            this.displayOverlay = true;
            this.noPresenterOverlay = true;
            this.autoUpdate = true;

            Logger.Trace("Init: SettingManager");
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets singleton public access
        /// </summary>
        public static SettingManager Instance
        {
            get
            {
                return instance ?? (instance = new SettingManager());
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether auto update.
        /// </summary>
        [XmlElement]
        public bool AutoUpdate
        {
            get
            {
                return this.autoUpdate;
            }

            set
            {
                this.autoUpdate = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether can minimize to tray.
        /// </summary>
        [XmlElement]
        public bool CanMinimizeToTray
        {
            get
            {
                return this.canMinimizeToTray;
            }

            set
            {
                this.canMinimizeToTray = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether debug mode.
        /// </summary>
        [XmlElement]
        public bool DebugMode
        {
            get
            {
                return this.debugMode;
            }

            set
            {
                this.debugMode = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether display overlay.
        /// </summary>
        [XmlElement]
        public bool DisplayOverlay
        {
            get
            {
                return this.displayOverlay;
            }

            set
            {
                this.displayOverlay = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether display popup notifications.
        /// </summary>
        [XmlElement]
        public bool DisplayPopupNotifications
        {
            get
            {
                return this.displayPopupNotifications;
            }

            set
            {
                this.displayPopupNotifications = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets the gesture engine mapping.
        /// </summary>
        [XmlElement]
        public string GestureEngineMapping
        {
            get
            {
                return this.gestureEngineMapping;
            }

            set
            {
                this.gestureEngineMapping = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets the gesture engine type.
        /// </summary>
        [XmlElement]
        public int GestureEngineType
        {
            get
            {
                return this.gestureEngineType;
            }

            set
            {
                this.gestureEngineType = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets the language.
        /// </summary>
        [XmlElement]
        public int Language
        {
            get
            {
                return this.language;
            }

            set
            {
                this.language = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets the last update check.
        /// </summary>
        [XmlElement]
        public long LastUpdateCheck
        {
            get
            {
                return this.lastUpdateCheck;
            }

            set
            {
                this.lastUpdateCheck = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether move to tray.
        /// </summary>
        [XmlElement]
        public bool MoveToTray
        {
            get
            {
                return this.moveToTray;
            }

            set
            {
                this.moveToTray = value;

                this.SaveSettings();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether no presenter overlay.
        /// </summary>
        [XmlElement]
        public bool NoPresenterOverlay
        {
            get
            {
                return this.noPresenterOverlay;
            }

            set
            {
                this.noPresenterOverlay = value;

                this.SaveSettings();
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// Loads settings into setting manager
        /// </summary>
        /// <param name="useXmlParameter">
        /// Use xml parameter, default: false
        /// </param>
        public void LoadSettings(bool useXmlParameter = false)
        {
            Logger.Trace("Method: LoadSettings - UseXml: {0}", this.useXml);

            this.useXml = useXmlParameter;

            if (this.useXml)
            {
                this.LoadFromXmlFile(
                    Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "settings.xml");
            }
            else
            {
                this.LoadFromUserSettings();
            }
        }

        /// <summary>
        /// Saves settings stored in SettingManager
        /// </summary>
        public void SaveSettings()
        {
            Logger.Trace("Method: SaveSettings - UseXml: {0}", this.useXml);

            if (this.useXml)
            {
                this.SaveToXmlFile(
                    Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "settings.xml");
            }
            else
            {
                this.SaveToUserSettings();
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Loads settings from user settings configuration
        /// </summary>
        private void LoadFromUserSettings()
        {
            this.language = Properties.Settings.Default.Language;
            this.canMinimizeToTray = Properties.Settings.Default.CanMinimizeToTray;
            this.moveToTray = Properties.Settings.Default.MoveToTray;
            this.displayPopupNotifications = Properties.Settings.Default.DisplayPopupNotifications;
            this.displayOverlay = Properties.Settings.Default.DisplayOverlay;
            this.noPresenterOverlay = Properties.Settings.Default.NoPresenterOverlay;
            this.autoUpdate = Properties.Settings.Default.AutoUpdate;
            this.gestureEngineType = Properties.Settings.Default.GestureEngineType;
            this.debugMode = Properties.Settings.Default.DebugMode;
            this.gestureEngineMapping = Properties.Settings.Default.GestureEngineMapping;
            this.lastUpdateCheck = Properties.Settings.Default.LastUpdateCheck;
        }

        /// <summary>
        /// Loads settings from file
        /// </summary>
        /// <param name="file">
        /// File to load settings from
        /// </param>
        private void LoadFromXmlFile(string file)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(SettingManager));
            FileStream textWriter = new FileStream(file, FileMode.Open);
            SettingManager manager = (SettingManager)serializer.Deserialize(textWriter);

            instance = manager;

            textWriter.Close();
        }

        /// <summary>
        /// Saves current settings to configuration
        /// </summary>
        private void SaveToUserSettings()
        {
            Properties.Settings.Default.Language = this.language;
            Properties.Settings.Default.CanMinimizeToTray = this.canMinimizeToTray;
            Properties.Settings.Default.MoveToTray = this.moveToTray;
            Properties.Settings.Default.DisplayPopupNotifications = this.displayPopupNotifications;
            Properties.Settings.Default.DisplayOverlay = this.displayOverlay;
            Properties.Settings.Default.NoPresenterOverlay = this.noPresenterOverlay;
            Properties.Settings.Default.AutoUpdate = this.autoUpdate;
            Properties.Settings.Default.GestureEngineType = this.gestureEngineType;
            Properties.Settings.Default.DebugMode = this.debugMode;
            Properties.Settings.Default.GestureEngineMapping = this.gestureEngineMapping;
            Properties.Settings.Default.LastUpdateCheck = this.lastUpdateCheck;

            Properties.Settings.Default.Save();
        }

        /// <summary>
        /// Saves settings to file
        /// </summary>
        /// <param name="file">
        /// File to write settings to
        /// </param>
        private void SaveToXmlFile(string file)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(SettingManager));
            TextWriter textWriter = new StreamWriter(file);
            serializer.Serialize(textWriter, this);

            textWriter.Close();
        }

        #endregion
    }
}